package com.smart.community.complaint.service.impl;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.smart.community.commons.result.PageResult;
import com.smart.community.commons.utils.StringUtils;
import com.smart.community.complaint.dto.ComplaintDTO;
import com.smart.community.complaint.dto.ComplaintQueryDTO;
import com.smart.community.complaint.entity.Complaint;
import com.smart.community.complaint.mapper.ComplaintMapper;
import com.smart.community.complaint.service.IComplaintService;
import com.smart.community.complaint.vo.ComplaintVO;

import lombok.extern.slf4j.Slf4j;

/**
 * 投诉建议服务实现类
 * 
 * @author Wu.Liang
 * @version 1.0.0
 * @since 2025-06-26
 */
@Slf4j
@Service
public class ComplaintServiceImpl extends ServiceImpl<ComplaintMapper, Complaint> implements IComplaintService {

    @Autowired
    private ComplaintMapper complaintMapper;

    // ========================= 投诉提交查询接口 =========================

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long submitComplaint(ComplaintDTO complaintDTO) throws Exception {
        log.info("提交投诉建议，用户ID：{}，标题：{}", complaintDTO.getUserId(), complaintDTO.getTitle());

        // 验证提交参数
        if (!complaintDTO.validateSubmit()) {
            throw new IllegalArgumentException("投诉提交参数验证失败");
        }

        // 创建投诉实体
        Complaint complaint = new Complaint();
        BeanUtils.copyProperties(complaintDTO, complaint);

        // 设置投诉编号
        complaint.setComplaintNo(generateComplaintNo());

        // 设置提交时间
        complaint.setSubmitTime(LocalDateTime.now());

        // 设置初始状态
        complaint.setStatus(0); // 待处理
        complaint.setHandleStatus(0); // 未分配

        // 设置期望解决时间
        if (complaint.getExpectedSolveTime() == null) {
            complaint.setExpectedSolveTime(complaintDTO.calculateExpectedSolveTime());
        }

        // 设置是否匿名投诉
        complaint.setIsAnonymousBoolean(complaintDTO.getIsAnonymous());

        // 保存投诉
        boolean success = this.save(complaint);
        if (!success) {
            throw new RuntimeException("保存投诉失败");
        }

        log.info("投诉建议提交成功，投诉ID：{}", complaint.getId());
        return complaint.getId();
    }

    @Override
    public PageResult<ComplaintVO> pageComplaints(ComplaintQueryDTO queryDTO) throws Exception {
        log.info("分页查询投诉建议，查询条件：{}", queryDTO);

        // 创建分页对象
        Page<ComplaintVO> page = new Page<>(queryDTO.getCurrent(), queryDTO.getSize());

        // 执行分页查询
        IPage<ComplaintVO> result = complaintMapper.selectComplaintPage(
                page,
                queryDTO.getUserId(),
                queryDTO.getCommunityId(),
                queryDTO.getTitle(),
                queryDTO.getCategoryCode(),
                queryDTO.getStatus(),
                queryDTO.getUrgency(),
                queryDTO.getHandlerId(),
                queryDTO.getIsAnonymous(),
                queryDTO.getSatisfactionRate(),
                queryDTO.getStartTime(),
                queryDTO.getEndTime(),
                queryDTO.getSortField(),
                queryDTO.getSortOrder()
        );

        // 构建分页结果
        PageResult<ComplaintVO> pageResult = new PageResult<>();
        pageResult.setRecords(result.getRecords());
        pageResult.setTotal(result.getTotal());
        pageResult.setCurrent((int)result.getCurrent());
        pageResult.setSize((int)result.getSize());

        log.info("分页查询投诉建议成功，总记录数：{}", result.getTotal());
        return pageResult;
    }

    @Override
    public ComplaintVO getComplaintDetail(Long complaintId) throws Exception {
        log.info("获取投诉详情，投诉ID：{}", complaintId);

        if (complaintId == null) {
            throw new IllegalArgumentException("投诉ID不能为空");
        }

        ComplaintVO complaintVO = complaintMapper.selectComplaintDetail(complaintId);
        if (complaintVO == null) {
            throw new RuntimeException("投诉不存在");
        }

        log.info("获取投诉详情成功，投诉ID：{}", complaintId);
        return complaintVO;
    }

    @Override
    public List<ComplaintVO> getComplaintsByUserId(Long userId) throws Exception {
        log.info("获取用户投诉列表，用户ID：{}", userId);

        if (userId == null) {
            throw new IllegalArgumentException("用户ID不能为空");
        }

        List<ComplaintVO> complaints = complaintMapper.selectComplaintsByUserId(userId);

        log.info("获取用户投诉列表成功，用户ID：{}，数量：{}", userId, complaints.size());
        return complaints;
    }

    // ========================= 投诉管理接口 =========================

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateComplaint(Long complaintId, ComplaintDTO complaintDTO) throws Exception {
        log.info("更新投诉信息，投诉ID：{}", complaintId);

        if (complaintId == null) {
            throw new IllegalArgumentException("投诉ID不能为空");
        }

        // 检查投诉是否存在
        Complaint existingComplaint = this.getById(complaintId);
        if (existingComplaint == null) {
            throw new RuntimeException("投诉不存在");
        }

        // 检查是否可以更新
        if (!existingComplaint.canUpdate()) {
            throw new RuntimeException("当前状态不允许更新");
        }

        // 更新投诉信息
        BeanUtils.copyProperties(complaintDTO, existingComplaint);
        existingComplaint.setUpdateTime(LocalDateTime.now());

        boolean success = this.updateById(existingComplaint);
        if (!success) {
            throw new RuntimeException("更新投诉失败");
        }

        log.info("更新投诉信息成功，投诉ID：{}", complaintId);
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteComplaint(Long complaintId) throws Exception {
        log.info("删除投诉记录，投诉ID：{}", complaintId);

        if (complaintId == null) {
            throw new IllegalArgumentException("投诉ID不能为空");
        }

        // 检查投诉是否存在
        Complaint complaint = this.getById(complaintId);
        if (complaint == null) {
            throw new RuntimeException("投诉不存在");
        }

        boolean success = this.removeById(complaintId);
        if (!success) {
            throw new RuntimeException("删除投诉失败");
        }

        log.info("删除投诉记录成功，投诉ID：{}", complaintId);
        return true;
    }

    // ========================= 投诉处理接口 =========================

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean handleComplaint(Long complaintId, ComplaintDTO complaintDTO) throws Exception {
        log.info("处理投诉，投诉ID：{}", complaintId);

        if (complaintId == null) {
            throw new IllegalArgumentException("投诉ID不能为空");
        }

        // 验证处理参数
        if (!complaintDTO.validateHandle()) {
            throw new IllegalArgumentException("投诉处理参数验证失败");
        }

        // 检查投诉是否存在
        Complaint complaint = this.getById(complaintId);
        if (complaint == null) {
            throw new RuntimeException("投诉不存在");
        }

        // 检查是否可以处理
        if (!complaint.canHandle()) {
            throw new RuntimeException("当前状态不允许处理");
        }

        // 更新处理信息
        complaint.setProcessStep(complaintDTO.getProcessStep());
        complaint.setHandleResult(complaintDTO.getProcessResult());
        complaint.setHandleTime(LocalDateTime.now());
        complaint.setHandleStatus(2); // 处理中
        complaint.setStatus(1); // 处理中
        complaint.setUpdateTime(LocalDateTime.now());

        boolean success = this.updateById(complaint);
        if (!success) {
            throw new RuntimeException("处理投诉失败");
        }

        log.info("处理投诉成功，投诉ID：{}", complaintId);
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean assignHandler(Long complaintId, Long handlerId) throws Exception {
        log.info("分配投诉处理人，投诉ID：{}，处理人ID：{}", complaintId, handlerId);

        if (complaintId == null || handlerId == null) {
            throw new IllegalArgumentException("投诉ID和处理人ID不能为空");
        }

        // 检查投诉是否存在
        Complaint complaint = this.getById(complaintId);
        if (complaint == null) {
            throw new RuntimeException("投诉不存在");
        }

        // 更新处理人信息
        complaint.setHandlerId(handlerId);
        complaint.setAssignTime(LocalDateTime.now());
        complaint.setHandleStatus(1); // 已分配
        complaint.setUpdateTime(LocalDateTime.now());

        boolean success = this.updateById(complaint);
        if (!success) {
            throw new RuntimeException("分配处理人失败");
        }

        log.info("分配投诉处理人成功，投诉ID：{}，处理人ID：{}", complaintId, handlerId);
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean solveComplaint(Long complaintId, String solution) throws Exception {
        log.info("解决投诉，投诉ID：{}", complaintId);

        if (complaintId == null || StringUtils.isEmpty(solution)) {
            throw new IllegalArgumentException("投诉ID和解决方案不能为空");
        }

        // 检查投诉是否存在
        Complaint complaint = this.getById(complaintId);
        if (complaint == null) {
            throw new RuntimeException("投诉不存在");
        }

        // 更新解决信息
        complaint.setSolution(solution);
        complaint.setActualSolveTime(LocalDateTime.now());
        complaint.setStatus(2); // 已解决
        complaint.setHandleStatus(3); // 已完成
        complaint.setUpdateTime(LocalDateTime.now());

        boolean success = this.updateById(complaint);
        if (!success) {
            throw new RuntimeException("解决投诉失败");
        }

        log.info("解决投诉成功，投诉ID：{}", complaintId);
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean closeComplaint(Long complaintId, String remark) throws Exception {
        log.info("关闭投诉，投诉ID：{}", complaintId);

        if (complaintId == null) {
            throw new IllegalArgumentException("投诉ID不能为空");
        }

        // 检查投诉是否存在
        Complaint complaint = this.getById(complaintId);
        if (complaint == null) {
            throw new RuntimeException("投诉不存在");
        }

        // 检查是否可以关闭
        if (!complaint.canClose()) {
            throw new RuntimeException("当前状态不允许关闭");
        }

        // 更新关闭信息
        complaint.setRemark(remark);
        complaint.setStatus(3); // 已关闭
        complaint.setUpdateTime(LocalDateTime.now());

        boolean success = this.updateById(complaint);
        if (!success) {
            throw new RuntimeException("关闭投诉失败");
        }

        log.info("关闭投诉成功，投诉ID：{}", complaintId);
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean reopenComplaint(Long complaintId, String reason) throws Exception {
        log.info("投诉重开，投诉ID：{}", complaintId);

        if (complaintId == null || StringUtils.isEmpty(reason)) {
            throw new IllegalArgumentException("投诉ID和重开原因不能为空");
        }

        // 检查投诉是否存在
        Complaint complaint = this.getById(complaintId);
        if (complaint == null) {
            throw new RuntimeException("投诉不存在");
        }

        // 检查是否可以重开
        if (!complaint.canReopen()) {
            throw new RuntimeException("当前状态不允许重开");
        }

        // 更新重开信息
        complaint.setRemark(reason);
        complaint.setStatus(0); // 待处理
        complaint.setHandleStatus(0); // 未分配
        complaint.setUpdateTime(LocalDateTime.now());

        boolean success = this.updateById(complaint);
        if (!success) {
            throw new RuntimeException("投诉重开失败");
        }

        log.info("投诉重开成功，投诉ID：{}", complaintId);
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean followupComplaint(Long complaintId, Integer satisfactionRate, String followupResult) throws Exception {
        log.info("回访投诉，投诉ID：{}", complaintId);

        if (complaintId == null || satisfactionRate == null || StringUtils.isEmpty(followupResult)) {
            throw new IllegalArgumentException("投诉ID、满意度评分和回访结果不能为空");
        }

        // 验证回访参数
        if (satisfactionRate < 1 || satisfactionRate > 5) {
            throw new IllegalArgumentException("满意度评分必须在1-5之间");
        }

        // 检查投诉是否存在
        Complaint complaint = this.getById(complaintId);
        if (complaint == null) {
            throw new RuntimeException("投诉不存在");
        }

        // 检查是否可以回访
        if (!complaint.canFollowup()) {
            throw new RuntimeException("当前状态不允许回访");
        }

        // 更新回访信息
        complaint.setSatisfactionRating(satisfactionRate);
        complaint.setFollowupResult(followupResult);
        complaint.setFollowupTime(LocalDateTime.now());
        complaint.setUpdateTime(LocalDateTime.now());

        boolean success = this.updateById(complaint);
        if (!success) {
            throw new RuntimeException("回访投诉失败");
        }

        log.info("回访投诉成功，投诉ID：{}", complaintId);
        return true;
    }

    // ========================= 投诉统计接口 =========================

    @Override
    public Map<String, Object> getComplaintStatistics(Long communityId) throws Exception {
        log.info("获取投诉统计信息，社区ID：{}", communityId);

        if (communityId == null) {
            throw new IllegalArgumentException("社区ID不能为空");
        }

        Map<String, Object> statistics = complaintMapper.selectComplaintStatistics(communityId);

        log.info("获取投诉统计信息成功，社区ID：{}", communityId);
        return statistics;
    }

    @Override
    public List<ComplaintVO> getTimeoutComplaints() throws Exception {
        log.info("获取超时投诉列表");

        List<ComplaintVO> complaints = complaintMapper.selectTimeoutComplaints();

        log.info("获取超时投诉列表成功，数量：{}", complaints.size());
        return complaints;
    }

    @Override
    public List<ComplaintVO> getPendingFollowupComplaints() throws Exception {
        log.info("获取待回访投诉列表");

        List<ComplaintVO> complaints = complaintMapper.selectPendingFollowupComplaints();

        log.info("获取待回访投诉列表成功，数量：{}", complaints.size());
        return complaints;
    }

    // ========================= 缓存管理接口 =========================

    @Override
    public void clearComplaintCache(Long communityId) throws Exception {
        log.info("清除投诉缓存，社区ID：{}", communityId);

        // TODO: 实现缓存清除逻辑
        // 这里可以清除Redis缓存或其他缓存

        log.info("清除投诉缓存成功，社区ID：{}", communityId);
    }

    // ========================= 私有方法 =========================

    /**
     * 生成投诉编号
     * 
     * @return 投诉编号
     */
    private String generateComplaintNo() {
        return "TS" + System.currentTimeMillis() + UUID.randomUUID().toString().substring(0, 8).toUpperCase();
    }
}
